/*-----------------------------------------------------------------------------------*/
/* Nuvoton Electronics Corporation confidential                                      */
/*                                                                                   */
/* Copyright (c) 2007 by Nuvoton Electronics Corporation                             */
/* All rights reserved                                                               */
/*                                                                                   */
/*-----------------------------------------------------------------------------------*/
/* File Contents:                                                                    */
/*   uart_demo.c                                                                     */
/*                                                                                   */
/* This file contains:                                                               */
/*                                                                                   */
/* Project:                                                                          */
/*                                                                                   */
/* Remark:                                                                           */
/*   1. UART test items without UART0, it's used by system library sysprintf().      */
/*   2. UART channel 1 can't be tested on NUC900 EV board. It's H/W issue.          */
/*                                                                                   */
/*-----------------------------------------------------------------------------------*/ 

#ifdef ECOS 
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "kapi.h"
#include "diag.h"
#include "wbio.h"
#else 
#include <stdio.h>
#include <string.h>
#include "wblib.h"
#endif

#include "nuc900_uart.h"


/* debug information */
//#define UARTMSG  /* ..... don't define it */

#ifdef ECOS
#define uartprintf		diag_printf
#define uartgetchar		diag_getc
#else
#define uartprintf		sysprintf
#define uartgetchar		sysGetChar
#endif 

#ifdef ECOS
static cyg_handle_t  	thread_handle;
static cyg_thread 		thread;
#define STACKSIZE		(128*1024)
static UINT8            _Statck[STACKSIZE];
#endif


#define TXSIZE		0x2800  /* 10Kbyte */
#define RXSIZE		0x2800  /* 10Kbyte */

static UINT8 RX_Test[500];

//static UINT8 TX_Test[] = "0123456789";
static UINT8 TX_Test[] = "1111111111";

static 	UART_T param;

//------------------------- Program -------------------------//
#ifdef UARTMSG
static VOID UART_ShowErrInfo(INT errno) 
{
	UINT32 err = 0;
	
	switch(errno)
	{
		case 0:
			uartprintf("\nSuccess\n");	
			break;		
		case UART_ENOTTY:
			uartprintf("\nCommand not support\n");	
			break;						
		case UART_ENODEV:	
			uartprintf("\nUART channel number out of range\n");	
			break;			
		case UART_EIO:		
			uartprintf("\nRead or Write error\n");	
			break;
	
		default:
			uartprintf("\nReturn value [%d]\n\n", errno);	return;
	}	

	/* Get more detail error information */
	uartIoctl(param.ucUartNo, UART_IOC_GETERRNO, (UINT32) &err, 0);
	uartprintf("UART driver error number [%d]\n", err);
}	
#endif

#ifdef ECOS
void uartExample (cyg_addrword_t tdata)
#else
void uartExample (VOID)
#endif
{
	int ch, retval, len, reccnt = 0, i, err = 0;
	
	uartprintf("\n\nMake sure the H/W configuration of different UART channel!\n");
	while(1)
	{
		/* Select UART channel */
		uartprintf("\n Select UART channel [1/2/3/4]\n");
		ch = uartgetchar();
		if ( (ch >= '1') && (ch <= '4') ) 
			break;	
	}
	uartprintf(" UART[%d] selected\n", ch - 0x30);
	
	/* configure UART */
	param.uFreq = 15000000;
	param.uBaudRate = 115200; 
	param.ucUartNo = ch - 0x30;  
	param.ucDataBits = DATA_BITS_8;
	param.ucStopBits = STOP_BITS_1;
	param.ucParity = PARITY_NONE;
	param.ucRxTriggerLevel = LEVEL_1_BYTE;	
	retval = uartOpen(&param); 
	if(retval != 0) 
	{
		uartprintf("Open UART error!\n");
		return;
	}
	
	/* set TX interrupt mode */
	retval = uartIoctl(param.ucUartNo, UART_IOC_SETTXMODE, UARTINTMODE, 0);
	if (retval != 0) 
	{
		uartprintf("Set TX interrupt mode fail!\n");
		return;	
	}
	
	/* set RX interrupt mode */
	retval = uartIoctl(param.ucUartNo, UART_IOC_SETRXMODE, UARTINTMODE, 0);
	if (retval != 0) 
	{
		uartprintf("Set RX interrupt mode fail!\n");
		return;	
	}
	
	while(1)
	{
		uartprintf("\n Select TX/RX test [0/1]\n");
		ch = uartgetchar();
		if ( (ch == '1') || (ch == '0') ) 
			break;	
	}
		
	if (ch == '0')	
	{
		/* TX test */
		uartprintf("\n Any key start to TX test\n");
		ch = uartgetchar();			
		len = strlen((PINT8) TX_Test);
		while(1)
		{
			retval = uartWrite(param.ucUartNo, TX_Test, len);
			if(retval < 0)
			{
                /* buffer full case */                				
#ifdef UARTMSG                
				UART_ShowErrInfo(retval);  /* ..... it affects the TX process ? */
#endif				
            }
			else if (retval == len)
			{
				reccnt += retval;

#ifndef UARTMSG 				
				uartprintf(" TX[%d]\r", reccnt);  /* if printf this message, the TX speed will slow */
#endif				
				
				if (reccnt >= TXSIZE)
				{
					uartprintf("\n\n TX test complete [%d] bytes transmitted\n", reccnt);	
					break;	
				}
			}
		}		
	}
	else
	{
		/* RX test */
		uartprintf("\n Any key start to RX test ...\n");
		uartprintf("    Should receive [%d] bytes\n", RXSIZE);
		ch = uartgetchar();		
		while(1)
		{
			/* 
				Don't printf any message that occur data lost. The RX buffer full will be occurred. 
			*/
			retval = uartRead(param.ucUartNo, RX_Test, 500);
			if(retval <= 500) 
			{
				reccnt += retval;
				if (retval != 0)
				{
					for (i = 0; i < retval; i++)
					{
						if (RX_Test[i] != 0x31)	
							uartprintf("%d[%x]\n", i + 1, RX_Test[i]);
					}	
				}
				
				if (reccnt >= RXSIZE)
				{
					uartprintf("\n RX test complete [%d] bytes received\n", reccnt);	
					break;	
				}	
			}
			else
				err++;
		}		
	}
	
	return;	
}

int main (VOID)
{
	//int i;
	
#ifdef ECOS
	cyg_thread_create(22, uartExample, 0, "uartdemo", _Statck, STACKSIZE, &thread_handle, &thread);
	cyg_thread_resume(thread_handle);
#else
	uartExample();
	//for (i = 0; i < 0x10000; i++);  /* delay for TX complete */
#endif	
	
	return 0;
}
